﻿/**
* jQuery EasyUI 1.4.3
* Copyright (c) 2009-2015 www.jeasyui.com. All rights reserved.
*
* Licensed under the GPL license: http://www.gnu.org/licenses/gpl.txt
* To use it on other terms please contact us at info@jeasyui.com
* http://www.jeasyui.com/license_commercial.php
*
* jQuery EasyUI treegrid 扩展
* jeasyui.extensions.treegrid.operateRow.js
* 开发 流云
* 由 落阳 整理
* 最近更新：2016-03-11
*
* 依赖项：
*   1、jquery.jdirk.js
*   2、jeasyui.extensions.treegrid.getRowInfo.js
*   3、jeasyui.extensions.treegrid.selectCheck.js
*   4、jeasyui.extensions.treegrid.checkPostion.js
*   5、jeasyui.extensions.treegrid.getCellInfo.js
*
* Copyright (c) 2016 ChenJianwei personal All rights reserved.
*/
(function ($) {

    $.util.namespace("$.fn.treegrid.extensions");


    $.extend($.fn.treegrid.extensions, {
        remove: $.fn.treegrid.methods.remove,
        append: $.fn.treegrid.methods.append,
        insert: $.fn.treegrid.methods.insert,
        update: $.fn.treegrid.methods.update
    });
    var removeRow = function (target, param) {
        var t = $(target), state = $.data(target, "treegrid"), opts = state.options, row;
        if (!$.isFunction(param)) {
            row = t.treegrid("find", param);
        }
        else {
            var rows = t.treegrid("getRows", true);
            row = $.array.first(rows, param);
        }
        if (row && $.isFunction(opts.onBeforeRemove) && opts.onBeforeRemove.call(target, row) != false) {
            $.fn.treegrid.extensions.remove.call(t, t, row[opts.idField]);
            $.array.remove(state.hiddenRows, row, function (item1, item2) { return item1[opts.idField] == item2[opts.item2]; });
            if ($.isFunction(opts.onRemove)) { opts.onRemove.call(target, row); }
        }
    };

    var removeRows = function (target, param) {
        var isArray = $.array.likeArray(param) && !$.util.isString(param);
        if (isArray) { $.each(param, function (index, val) { removeRow(target, val); }); return; }
        if ($.isFunction(param)) {
            var t = $(target), state = $.data(target, "treegrid"), opts = state.options, rows = t.treegrid("getRows", true), data = $.array.filter(rows, param);
            $.each(data, function (index, row) {
                if ($.isFunction(opts.onBeforeRemove) && opts.onBeforeRemove.call(target, row) != false) {
                    $.fn.treegrid.extensions.remove.call(t, t, row[opts.idField]);
                    $.array.remove(state.hiddenRows, row, function (item1, item2) { return item1[opts.idField] == item2[opts.item2]; });
                    if ($.isFunction(opts.onRemove)) { opts.onRemove.call(target, row); }
                }
            });
        }
    };

    var hideRow = function (target, param) {
        var t = $(target), state = $.data(target, "treegrid"), opts = state.options;
        var row = t.treegrid("find", param), id = row ? row[opts.idField] : null;
        if (id == null) { return; }

        $.array.unique(state.hiddenRows, row, t.treegrid("getChildren", id));
        t.treegrid("unselectRow", { id: id, cascade: true }).treegrid("uncheckRow", { id: id, cascade: true });
        t.treegrid("getRowDom", { id: id, cascade: true }).addClass("datagrid-row-hidden");
    };

    var showRow = function (target, param) {
        var t = $(target), state = $.data(target, "treegrid"), opts = state.options;
        var row = t.treegrid("find", param), id = row ? row[opts.idField] : null;
        if (id == null) { return; }
        var rows = $.array.merge(t.treegrid("getChildren", id), row);
        $.each(rows, function (index, item) {
            $.array.remove(state.hiddenRows, this);
        });
        t.treegrid("getRowDom", { id: id, cascade: true }).removeClass("datagrid-row-hidden");
    };

    var hideRows = function (target, param) {
        var t = $(target), state = $.data(target, "treegrid"), opts = state.options;
        if (param == true) {
            var rows = t.treegrid("getRows", true);
            $.array.clear(state.hiddenRows);
            $.array.copy(state.hiddenRows, rows);
            t.treegrid("unselectAll").treegrid("uncheckAll");
            $.each(rows, function (i, n) {
                t.treegrid("getRowDom", n[opts.idField]).addClass("datagrid-row-hidden");
            });
        } else {
            var rows = t.treegrid("findRows", param);
            $.each(rows, function (i, row) {
                var id = row ? row[opts.idField] : null; if (id == null) { return; }
                $.array.unique(state.hiddenRows, row, t.treegrid("getChildren", id));
                t.treegrid("unselectRow", { id: id, cascade: true }).treegrid("uncheckRow", { id: id, cascade: true });
                t.treegrid("getRowDom", { id: id, cascade: true }).addClass("datagrid-row-hidden");
            });
        }
    };

    var showRows = function (target, param) {
        var t = $(target), state = $.data(target, "treegrid"), opts = state.options;
        if (param == true) {
            var rows = t.treegrid("getRows", true);
            $.array.clear(state.hiddenRows);
            $.each(rows, function (i, n) {
                t.treegrid("getRowDom", n[opts.idField]).removeClass("datagrid-row-hidden");
            });
        } else {
            var rows = t.treegrid("findRows", param);
            $.each(rows, function (i, row) {
                var id = row ? row[opts.idField] : null; if (id == null) { return; }
                var ps = $.array.merge(t.treegrid("getChildren", id), row);
                $.each(ps, function () { $.array.remove(state.hiddenRows, this); });
                t.treegrid("getRowDom", { id: id, cascade: true }).removeClass("datagrid-row-hidden");
            });
        }
    };

    var getHiddenRows = function (target, cascade) {
        var t = $(target), state = $.data(target, "treegrid");
        if (cascade) { return state.hiddenRows; }
        var roots = t.treegrid("getRoots");
        return $.array.filter(state.hiddenRows, function (val) { return $.array.contains(roots, val); });
    };

    var moveRow = function (target, param) {
        if (!param || !param.source || !param.target || !param.point) { return; }
        if (!$.array.contains(["append", "top", "bottom"], param.point)) { param.point = "append"; }
        var t = $(target),
            sourceNode = t.treegrid("find", param.source), targetNode = t.treegrid("find", param.target);
        if (!sourceNode || !targetNode || sourceNode == targetNode) { return; }

        if (t.treegrid("isParent", { id1: param.source, id2: param.target })) { return; }

        var state = $.data(target, "treegrid"), opts = state.options;
        if ($.isFunction(opts.onBeforeMove) && opts.onBeforeMove.call(target, targetNode, sourceNode, param.point) == false) { return; }

        var node = t.treegrid("pop", param.source);
        switch (param.point) {
            case "append": t.treegrid("append", { parent: param.target, data: [node] }); break;
            case "top": t.treegrid("insert", { before: param.target, data: node }); break;
            case "bottom": t.treegrid("insert", { after: param.target, data: node }); break;
            default: t.treegrid("append", { parent: param.target, data: [node] }); break;
        }
        if (node && $.isFunction(opts.onMove)) { opts.onMove.call(target, targetNode, sourceNode, param.point); }
    };

    var shiftRow = function (target, param) {
        if (!param || !param.id || !param.point || !$.array.contains(["up", "upLevel", "down", "downLevel"], param.point)) { return; }
        var t = $(target), node;
        switch (param.point) {
            case "up": node = t.treegrid("prevRow", param.id); break;
            case "upLevel": node = t.treegrid("getParent", param.id); break;
            case "down": node = t.treegrid("nextRow", param.id); break;
            case "downLevel": node = t.treegrid("prevRow", param.id); break;
            default: break;
        }
        if (!node) { return; }
        var opts = t.treegrid("options");
        t.treegrid("moveRow", { target: node[opts.idField], source: param.id, point: param.point == "up" ? "top" : (param.point == "downLevel" ? "append" : "bottom") });
    };




    function initHeaderFiltersData(t, opts) {
        var target = t[0],
            state = $.data(target, "treegrid");
        state.hiddenRows = [];
    }

    function initializeExtensions(target) {
        var t = $(target),
            state = $.data(target, "treegrid"),
            opts = state.options;

        initHeaderFiltersData(t, opts);
    }

    var _treegrid = $.fn.treegrid.extensions._treegrid = $.fn.treegrid;
    $.fn.treegrid = function (options, param) {
        if (typeof options == "string") {
            return _treegrid.apply(this, arguments);
        }
        options = options || {};
        return this.each(function () {
            var jq = $(this),
                isInited = $.data(this, "treegrid") ? true : false,
                opts = isInited ? options : $.extend({},
                        $.fn.treegrid.parseOptions(this), options);
            _treegrid.call(jq, opts, param);
            if (!isInited) {
                initializeExtensions(this);
            }
        });
    };
    $.union($.fn.treegrid, _treegrid);



    var defaults = $.fn.treegrid.extensions.defaults = {

        //  扩展 easyui-treegrid 的自定义事件；该事件表示执行 remove 或 removeRow 方法前所触发的动作；该事件回调函数提供如下两个参数：
        //      row:    表示要进行移除操作的行数据对象；
        //  该事件函数中的 this 指向当前 easyui-treegrid 的 DOM 对象(非 jQuery 对象)；
        //  备注：如果该事件回调函数返回 false，则立即取消即将要执行的移除操作。
        onBeforeRemove: function (row) { },

        //  扩展 easyui-treegrid 的自定义事件；该事件表示执行 remove 或 removeRow 方法后所触发的动作；该事件回调函数提供如下两个参数：
        //      row:    表示要进行移除操作的行数据对象；
        //  该事件函数中的 this 指向当前 easyui-treegrid 的 DOM 对象(非 jQuery 对象)；
        onRemove: function (row) { },

        //  扩展 easyui-treegrid 的自定义事件；该事件表示执行 moveRow 方法前所触发的动作；该事件回调函数提供如下两个参数：
        //      row:    表示要进行移动操作的行数据对象；
        //  该事件函数中的 this 指向当前 easyui-treegrid 的 DOM 对象(非 jQuery 对象)；
        //  备注：如果该事件回调函数返回 false，则立即取消即将要执行的移动操作。
        onBeforeMove: function (targetRow, sourceRow, point) { },

        //  扩展 easyui-treegrid 的自定义事件；该事件表示执行 moveRow 方法后所触发的动作；该事件回调函数提供如下两个参数：
        //      row:    表示要进行移动操作的行数据对象；
        //  该事件函数中的 this 指向当前 easyui-treegrid 的 DOM 对象(非 jQuery 对象)；
        onMove: function (targetRow, sourceRow, point) { }
    };

    var methods = $.fn.treegrid.extensions.methods = {

        //  重写 easyui-treegrid 的源生方法 remove，使之功能更加丰富；
        //  删除 easyui-treegrid 中当前页指定的节点以及它所有的子节点；参数 param 表示要删除的内容；该参数可以是以下三种类型：
        //      表示要删除的行数据的 idField(主键) 字段值；
        //      Function 类型，该回调函数签名为 function(row, index, rows)，其中 row 表示行数据对象、index 表示行索引号、rows 表示当前 easyui-treegrid 所有节点对象集合；
        //          如果 param 参数为 Function 类型，则 deleteRow 方法会对当前 easyui-treegrid 的当前页的每一行数据调用该回调函数；
        //          当回调函数返回 true 时，则表示查找到了需要被删除的行，deleteRow 方法将会删除该行数据并立即停止和跳出循环操作；
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 链式对象。
        remove: function (jq, param) { return jq.each(function () { removeRow(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；删除 easyui-treegrid 中当前页指定的节点以及它所有的子节点；
        //  同 remove 方法。
        removeRow: function (jq, param) { return jq.each(function () { removeRow(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；删除多行数据，参数 param 表示要删除的内容；该参数可以是以下两种类型：
        //      Function 类型，该回调函数签名为 function(row, index, rows)，其中 row 表示行数据对象、index 表示行索引号、rows 表示当前 easyui-treegrid 所有节点对象集合；
        //          如果 param 参数为 Function 类型，则 deleteRows 方法会对当前 easyui-treegrid 的当前页的每一行数据调用该回调函数；
        //          当回调函数返回 true 时，则表示查找到了需要被删除的行，deleteRows 方法将会删除该行数据，并遍历下一行数据直至数数据集的末尾；
        //      Array 类型，数组中的每一项目均表示要删除的行的行索引号或者 idField(主键) 字段值。
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 链式对象。
        removeRows: function (jq, param) { return jq.each(function () { removeRows(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；隐藏当前页数据中指定行的数据；该方法的参数 param 可以是以下两种类型：
        //      待查找的行数据的 idField(主键) 字段值；
        //      function 类型，该回调函数签名为 function(row, index, rows)，其中 row 表示行数据对象、index 表示行索引号、rows 表示当前 easyui-treegrid 所有节点对象集合；
        //          如果 param 参数为 function 类型，则 findRow 方法会对当前 easyui-treegrid 的当前页的每一行数据调用该回调函数；
        //          当回调函数返回 true 时，则表示找到需要查找的结果，立即停止循环调用并隐藏该行数据；
        //          如果回调函数始终未返回 true，则该回调函数会一直遍历 rows 直到最后。
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 链式对象。
        hideRow: function (jq, param) { return jq.each(function () { hideRow(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；显示当前页数据中指定行的数据；该方法的参数 param 可以是以下两种类型：
        //      待查找的行数据的 idField(主键) 字段值；
        //      function 类型，该回调函数签名为 function(row, index, rows)，其中 row 表示行数据对象、index 表示行索引号、rows 表示当前 easyui-treegrid 所有节点对象集合；
        //          如果 param 参数为 function 类型，则 findRow 方法会对当前 easyui-treegrid 的当前页的每一行数据调用该回调函数；
        //          当回调函数返回 true 时，则表示找到需要查找的结果，立即停止循环调用并显示该行数据；
        //          如果回调函数始终未返回 true，则该回调函数会一直遍历 rows 直到最后。
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 链式对象。
        showRow: function (jq, param) { return jq.each(function () { showRow(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；隐藏当前页数据中指定多行的数据；该方法的参数 param 可以是以下三种类型：
        //      Function 类型，该回调函数签名为 function(row, index, rows)，其中 row 表示行数据对象、index 表示行索引号、rows 表示当前 easyui-treegrid 所有节点对象集合；
        //          如果 param 参数为 Function 类型，则 hideRows 方法会对当前 easyui-treegrid 的当前页的每一行数据调用该回调函数；
        //          当回调函数返回 true 时，则该行数据将会被隐藏；
        //      Array 类型，数组中的每一项都可以定义为如下类型：
        //          待查找的行数据的 idField(主键) 字段值；
        //          Function 类型；具体回调函数签名参考 hideRow 方法中 param 参数为 function 类型时的定义；
        //          当 param 参数定义为 Array 类型时，则 hideRows 方法会对数组中的每一项循环调用 hideRow 方法；
        //      Boolean 类型且为 true：则 hideRows 将会隐藏当前页的所有数据。
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 链式对象。
        hideRows: function (jq, param) { return jq.each(function () { hideRows(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；显示当前页数据中指定多行的数据；该方法的参数 param 可以是以下三种类型：
        //      Function 类型，该回调函数签名为 function(row, index, rows)，其中 row 表示行数据对象、index 表示行索引号、rows 表示当前 easyui-treegrid 所有节点对象集合；
        //          如果 param 参数为 Function 类型，则 showRows 方法会对当前 easyui-treegrid 的当前页的每一行数据调用该回调函数；
        //          当回调函数返回 true 时，则该行数据将会被显示；
        //      Array 类型，数组中的每一项都可以定义为如下类型：
        //          待查找的行数据的 idField(主键) 字段值；
        //          Function 类型；具体回调函数签名参考 showRow 方法中 param 参数为 function 类型时的定义；
        //          当 param 参数定义为 Array 类型时，则 showRows 方法会对数组中的每一项循环调用 showRow 方法；
        //      Boolean 类型且为 true：则 showRows 将会显示当前页的所有数据。
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 链式对象。
        showRows: function (jq, param) { return jq.each(function () { showRows(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；获取当前页所有隐藏的行数据所构成的一个 Array 对象；该方法的参数 cascade 定义为如下类型：
        //      Boolean 类型，默认为 false，表示是否连同子级节点数据一并返回；
        //  返回值：返回一个 Array 数组对象，数组中的每一个元素都表示一个 node；
        //      如果 cascade 为 true，则返回隐藏的行数据中所有根节点以及子节点合并所构成的一个数组；
        //      如果 cascade 为 false，则仅返回隐藏的行数据中所有根节点数据；
        //      如果 easyui-treegrid 的当前页没有隐藏的行数据，则返回一个长度为 0 的数组。
        getHiddenRows: function (jq, cascade) { return getHiddenRows(jq[0], cascade); },

        //  扩展 easyui-treegrid 的自定义方法；移动指定的节点到另一个位置；该方法定义如下参数：
        //      param:   这是一个 JSON-Object，该对象定义如下属性：
        //          target: 表示目标位置的 tree-node 对象的 idField 值；
        //          source: 表示要移动的 tree-node 对象的 idField 值；
        //          point:  表示移动到目标节点 target 的位置，String 类型，可选的值包括：
        //              "append":   表示追加为目标节点 target 的子节点，默认值；
        //              "top":      表示移动到目标节点 target 的上一格位置；
        //              "bottom":   表示追加为目标节点 target 的下一格位置；
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 对象。
        moveRow: function (jq, param) { return jq.each(function () { moveRow(this, param); }); },

        //  扩展 easyui-treegrid 的自定义方法；移动指定节点的位置；该方法的参数 param 为一个 JSON-Object 类型对象，包含如下属性：
        //      id: 表示要移动的 tree-node 对象的 idField 值；
        //      point:  表示移动 target 的方式，String 类型，可选的值报错：
        //          "up":       表示将 target 所表示的 tree-node 移动到上一格位置；
        //          "upLevel":  表示将 target 所表示的 tree-node 移动到上一级的末尾；
        //          "down":     表示将 target 所表示的 tree-node 移动到下一格位置；
        //          "downLevel":表示将 target 所表示的 tree-node 移动到下一级的末尾；
        //          如果不定义该值或者该值为空或该值不是上面四个之一，则不进行任何操作；
        //  返回值：返回表示当前 easyui-treegrid 组件的 jQuery 对象。
        shiftRow: function (jq, param) { return jq.each(function () { shiftRow(this, param); }); }
    };


    $.extend($.fn.treegrid.defaults, defaults);
    $.extend($.fn.treegrid.methods, methods);

})(jQuery);